import { GameManager } from "./GameManager";
import Player from "./Player";


const { ccclass, property } = cc._decorator;


let DIR = cc.Enum({
    UP: 0,
    RIGHT: 1,
    DOWN: 2,
    LEFT: 3
});



@ccclass
export default class game extends cc.Component {

    private static instance: game = null;

    playerIndex = 0;
    palyerDir: number;
    enemyDir: number;
    playerTile: cc.Vec2[] = [];
    anotherPlayerTile: cc.Vec2;
    enemyTile: cc.Vec2;
    bombTile: cc.Vec2[] = [];
    panelShow: boolean = false;
    dir_vec2: cc.Vec2[] = [cc.v2(0, 32),
    cc.v2(32, 0),
    cc.v2(0, -32),
    cc.v2(-32, 0)]

    @property(cc.Node)
    player: cc.Node;

    @property(cc.Node)
    player1: cc.Node;

    @property(cc.Node)
    enemy: cc.Node;

    @property(cc.Node)
    endPanel: cc.Node;

    bomb: cc.Node;

    @property(cc.TiledLayer)
    mainLayer: cc.TiledLayer;

    @property(cc.TiledLayer)
    soilLayer: cc.TiledLayer;

    @property(cc.TiledLayer)
    hideLayer: cc.TiledLayer;

    @property(cc.TiledMap)
    map: cc.TiledMap;

    @property(cc.Prefab)
    bombPrefab: cc.Prefab;

    @property(cc.Prefab)
    bombExplodePrefab: cc.Prefab;

    @property(cc.Label)
    playerIndexLabel: cc.Label

    maxLayerX: number;
    maxLayerY: number;
    moveGridCount: number = 0;
    isDirVetical: boolean = false;

    moveLeft: boolean = false;
    moveDistance: number = 0;
    ran_dir: cc.Vec2 = cc.v2(32, 0);

    gameManager;

    socket;

    instance

    /**
     * 炸弹火力
     */
    bombPower: number = 5;

    players = {};

    public static getInstance(): game {
        if (this.instance == null) {
            this.instance = cc.find("map").getComponent(game);
            cc.director.once(cc.Director.EVENT_AFTER_SCENE_LAUNCH, () => {
                this.instance = null;
            });
        }
        return this.instance;
    }

    onLoad() {
        let that = this;
        this.gameManager = GameManager.Instance(GameManager);
        this.playerIndex= this.gameManager.playerIndex;
        that.playerIndexLabel.string = (Number(GameManager.Instance(GameManager).playerIndex)+1) + '号选手';
        
        this.gameManager.roomSocket.on('placebomb', function (bombPos) {
            that.placeBomb({}, bombPos);
        });
        this.player.getComponent(Player).playerIndex=0;
        this.player1.getComponent(Player).playerIndex=1;
        this.players[0] = this.player
        this.players[1] = this.player1
        this.gameManager.roomSocket.on('playermove', function (info) {
            let tmpInfo = JSON.parse(info);
            that.playerTile[tmpInfo.playerIndex] = cc.v2(tmpInfo.x, tmpInfo.y);
            let pos = that.mainLayer.getPositionAt(that.playerTile[tmpInfo.playerIndex]);
            if(tmpInfo.playerIndex == 0){
                that.player.setPosition(pos.x, pos.y)
            } else {
                that.player1.setPosition(pos.x, pos.y)
            }
        });

        this.gameManager.roomSocket.on('pickUpItem', function (info) {
            let tmpInfo = JSON.parse(info);
            that.hideLayer.setTileGIDAt(0, tmpInfo.x, tmpInfo.y);
        });


    }

    start() {
        this.loadMap();
        let self = this;
        this.map.node.on("exploded", function () {
            // 检查炸弹的上下左右是否是soil
            self.bombExplode();
            // 把炸弹移除掉
            self.map.node.removeChild(self.bomb);
        });

        this.maxLayerX = this.soilLayer.getLayerSize().width;
        this.maxLayerY = this.soilLayer.getLayerSize().height;
        //cc.director.getScheduler().schedule(this.enmeyMove, this, 1);
        //this.enemyDir = DIR.RIGHT;
    }

    getNodePos(targetNode:cc.Node,worldX,worldY){
        // 假设你要将世界坐标(worldX, worldY)转换为targetNode下的本地坐标
let worldPos = cc.v2(worldX, worldY);

// 将世界坐标转换为targetNode下的本地坐标
let localPos = targetNode.convertToNodeSpaceAR(worldPos);

// 打印结果
console.log(`世界坐标(${worldX}, ${worldY})在targetNode下的本地坐标为 (${localPos.x}, ${localPos.y})`);
return {x:localPos.x,y:localPos.y}
    }

    getTileWorldPos(x:number,y:number){
        // 获取指定格子的瓦片大小
        let tileSize = this.map.getTileSize();

        // 将格子坐标转换为像素坐标
        let pixelX = x * tileSize.width; 
        let pixelY = y * tileSize.height;

        // 将像素坐标转换为世界坐标
        let worldPos =  this.map.node.convertToWorldSpaceAR(cc.v2(pixelX, pixelY));
        return {x:worldPos.x,y:worldPos.y}
        
    }

    enmeyMove() {
        this.moveGridCount += 1;
        if (this.moveGridCount % 5 == 0) {
            let ran_num = Math.floor(Math.random() * 4);
            //this.ran_dir = this.dir_vec2[ran_num]
        }
        let targetTile;
        if (this.enemyDir == DIR.RIGHT) {
            targetTile = cc.v2(this.enemyTile.x + 2, this.enemyTile.y - 1)
        } else if (this.enemyDir == DIR.LEFT) {
            targetTile = cc.v2(this.enemyTile.x - 1, this.enemyTile.y - 1)
        } else if (this.enemyDir == DIR.UP) {
            targetTile = cc.v2(this.enemyTile.x, this.enemyTile.y - 2)
        } else {
            targetTile = cc.v2(this.enemyTile.x, this.enemyTile.y)
        }
        if (this.checkTileMoveable(targetTile)) {

            let moveBy = cc.moveBy(1, this.ran_dir);

            var callFunc = cc.callFunc(function () {
                this.enemyTile = this.getTilePos(cc.v2(this.enemy.x, this.enemy.y));
            }, this);

            var seq = cc.sequence(moveBy, callFunc);
            this.enemy.runAction(seq)

        } else {
            let ran_num = Math.floor(Math.random() * 4);
            this.ran_dir = this.dir_vec2[ran_num];
            this.enemyDir = ran_num;
            this.enemyTile = this.getTilePos(cc.v2(this.enemy.x, this.enemy.y));

        }
    }

    /**
     * 炸弹爆炸
     * 检测是否可以炸毁砖块
     */
    bombExplode() {
        let i: number;
        let bombExplodePrefab;
        let upPos: cc.Vec2;
        let downPos: cc.Vec2;
        let leftPos: cc.Vec2;
        let rightPos: cc.Vec2;
        let hasDestoryUp: boolean;
        let hasDestoryDown: boolean;
        let hasDestoryLeft: boolean;
        let hasDestoryRight: boolean;
        for (i = 1; i <= this.bombPower; i++) {
            upPos = cc.v2(this.bombTile[this.playerIndex].x, this.bombTile[this.playerIndex].y - i);
            downPos = cc.v2(this.bombTile[this.playerIndex].x, this.bombTile[this.playerIndex].y + i);
            leftPos = cc.v2(this.bombTile[this.playerIndex].x - i, this.bombTile[this.playerIndex].y);
            rightPos = cc.v2(this.bombTile[this.playerIndex].x + i, this.bombTile[this.playerIndex].y);
            if (i == 1) {
                hasDestoryUp = false;
                hasDestoryDown = false;
                hasDestoryRight = false;
                hasDestoryLeft = false;
                this.instantiateExplodeWave(bombExplodePrefab, upPos);
                this.instantiateExplodeWave(bombExplodePrefab, downPos, 180);
                this.instantiateExplodeWave(bombExplodePrefab, leftPos, 90);
                this.instantiateExplodeWave(bombExplodePrefab, rightPos, 270);
            }
            hasDestoryUp = this.destroyBlock(upPos, hasDestoryUp);
            hasDestoryDown = this.destroyBlock(downPos, hasDestoryDown);
            hasDestoryLeft = this.destroyBlock(leftPos, hasDestoryLeft);
            hasDestoryRight = this.destroyBlock(rightPos, hasDestoryRight);
        }
        this.checkEnemyDie();
        this.checkPlayerDie();
    }

    checkEnemyDie() {
        if ((this.enemyTile.x >= this.bombTile[this.playerIndex].x - this.bombPower && this.enemyTile.x <= this.bombTile[this.playerIndex].x + this.bombPower) && this.enemyTile.y - 1 == this.bombTile[this.playerIndex].y) {
            this.removeEnemy();
        }
        if ((this.enemyTile.y >= this.bombTile[this.playerIndex].y - this.bombPower && this.enemyTile.y <= this.bombTile[this.playerIndex].y + this.bombPower) && this.enemyTile.x == this.bombTile[this.playerIndex].x) {
            this.removeEnemy();
        }
    }

    checkPlayerDie() {
        let that = this;
        let msg = '';
        let textWrite:boolean;
        this.playerTile.forEach(function (pos, k) {
            textWrite = false;
            if ((pos.x >= that.bombTile[that.playerIndex].x - that.bombPower && pos.x <= that.bombTile[that.playerIndex].x + that.bombPower)
                && pos.y == that.bombTile[that.playerIndex].y) {
                    if(!textWrite){
                        msg+= (Number(k)+1)+'号死亡;'
                        textWrite= true;
                    }
               
            }
            if ((pos.y >= that.bombTile[that.playerIndex].y - that.bombPower && pos.y <= that.bombTile[that.playerIndex].y + that.bombPower)
                && pos.x == that.bombTile[that.playerIndex].x) {
                    if(!textWrite){
                        msg+= (Number(k)+1)+'号死亡;'
                        textWrite= true;
                    }
            }
        })

        this.endPanel.active = true;
        this.endPanel.getComponentInChildren(cc.Label).string = msg;

    }

    /**
     * 移除敌人
     */
    removeEnemy() {
        this.map.node.removeChild(this.enemy);
        this.enemyTile.x = 1000;
        this.enemyTile.y = 1000;
        this.enemy.position = cc.v2(10000, 10000);
    }

    /**
     * 生成炸弹冲击波
     * @param bombExplodePrefab 
     * @param pos 
     * @param angle 
     */
    instantiateExplodeWave(bombExplodePrefab, pos: cc.Vec2, angle = 0) {
        bombExplodePrefab = cc.instantiate(this.bombExplodePrefab);
        if (angle) {
            if (angle == 90) {
                bombExplodePrefab.setAnchorPoint(0.5, 0);
                bombExplodePrefab.angle = angle;
            } else if (angle == 180) {
                bombExplodePrefab.setAnchorPoint(0, 1);
            } else if (angle == 270) {
                bombExplodePrefab.angle = angle;
                bombExplodePrefab.setAnchorPoint(1, 0);
            }
        }
        bombExplodePrefab.setPosition(this.mainLayer.getPositionAt(this.bombTile[this.playerIndex].x, this.bombTile[this.playerIndex].y));
        bombExplodePrefab.height = 32 * this.bombPower;
        this.node.addChild(bombExplodePrefab);
    }

    /**
     * 破坏砖块
     * @param pos 
     * @param hasDestroy 
     */
    destroyBlock(pos: cc.Vec2, hasDestroy: boolean) {
        try {
            if (pos.x >= 0 && pos.y >= 0 && pos.x <= this.maxLayerX - 1 && pos.y <= this.maxLayerY - 1) {
                if (this.soilLayer.getTileGIDAt(pos) && !hasDestroy) {
                    hasDestroy = true;
                    this.soilLayer.setTileGIDAt(0, pos.x, pos.y);
                }
            }
        } catch (err) {
            cc.log(err)
        }

        return hasDestroy;
    }

    btnUp() {
        cc.log('currentIndex' + this.playerIndex)
        this.palyerDir = DIR.UP;
        let playerTargetTile = cc.v2(this.playerTile[this.playerIndex].x, this.playerTile[this.playerIndex].y - 1);
        this.tryMoveToTargetTile(playerTargetTile);
    }

    btnDown() {
        this.palyerDir = DIR.DOWN;
        let playerTargetTile = cc.v2(this.playerTile[this.playerIndex].x, this.playerTile[this.playerIndex].y + 1);
        this.tryMoveToTargetTile(playerTargetTile);
    }

    btnLeft() {
        this.palyerDir = DIR.LEFT;
        let playerTargetTile = cc.v2(this.playerTile[this.playerIndex].x - 1, this.playerTile[this.playerIndex].y);
        this.tryMoveToTargetTile(playerTargetTile);
    }

    btnRight() {
        this.palyerDir = DIR.RIGHT;
        let playerTargetTile = cc.v2(this.playerTile[this.playerIndex].x + 1, this.playerTile[this.playerIndex].y);
        this.tryMoveToTargetTile(playerTargetTile);
    }

    public getGridPonitToWordPoint(x,y){
        let worldPos = this.getTileWorldPos(x,y);
        let finalPos = this.getNodePos(this.map.node,worldPos.x,worldPos.y)
        return {x:finalPos.x,y:finalPos.y}
    }

    public tryMoveToTargetTile(newTile) {
        //检测mainLayer是否可以通过
        if (this.mainLayer.getTileGIDAt(newTile) || this.soilLayer.getTileGIDAt(newTile)) {//tile不为空，返回
            cc.log('This way is blocked!');
            return false;
        }
        if(this.players[this.playerIndex].isMoveing){
            //return false;
        }
        this.players[this.playerIndex].isMoveing = true;
       // let worldPos = this.getTileWorldPos(newTile.x,newTile.y);
        
        let finalPos =this.getGridPonitToWordPoint(newTile.x,newTile.y);
       // let oriPos = this.players[this.playerIndex].x,this.players[this.playerIndex]
        //cc.log("final:",finalPos.x,finalPos.y)
        // cc.tween(this.players[this.playerIndex])
        
        //     .to (1, { position: cc.v2(finalPos.x,finalPos.y) })
        //     .call(()=>{
        //         this.players[this.playerIndex].isMoveing = false;
        //     })
        //     .start()
        //cc.tween( this.players[this.playerIndex])
       
        this.playerTile[this.playerIndex] = newTile;
        let posInfo = new Object;
        posInfo.playerIndex = this.playerIndex;
        posInfo.x = newTile.x;
        posInfo.y = newTile.y;
        cc.log('------------------')
        this.gameManager.roomSocket.emit('playermove', JSON.stringify(posInfo));
        this.updatePlayerPos();
        let type: string = this.getTileType(this.hideLayer, this.playerTile[this.playerIndex]);
        if (type == 'door') {
            this.endPanel.active = true;
            this.endPanel.getComponentInChildren(cc.Label).string = '你赢了';
            this.panelShow = true;
        } else if (type == 'power') {
            this.bombPower += 1;
            this.hideLayer.setTileGIDAt(0, this.playerTile[this.playerIndex].x, this.playerTile[this.playerIndex].y);
            let tmpObject = new Object;
            tmpObject.x = this.playerTile[this.playerIndex].x;
            tmpObject.y = this.playerTile[this.playerIndex].y;
            this.socket.emit('pickUpItem', JSON.stringify(tmpObject));
        }
    }

    checkTileMoveable(newTile) {
        if (newTile.x >= 0 && newTile.y >= 0 && newTile.x <= this.maxLayerX - 1 && newTile.y <= this.maxLayerY - 1) {
            //检测mainLayer是否可以通过
            if (this.mainLayer.getTileGIDAt(newTile) || this.soilLayer.getTileGIDAt(newTile)) {//tile不为空，返回
                cc.log('This way is blocked!');
                return false;
            }
            return true;
        }
        cc.log('This way is blocked!');
        return false;
    }

    loadMap() {
        //获取对象层
        var objects = this.map.getObjectGroup('objects');
        //获取对象
        var playerObj = objects.getObject('player1');
        var playerObj1 = objects.getObject('player2');
        var enemyObj = objects.getObject('enemy');
        //获取坐标
        var playerPos = cc.v2(playerObj.x, playerObj.y);
        var enemyPos = cc.v2(enemyObj.x, enemyObj.y);
        //设置玩家和敌人瓦片坐标
        this.playerTile[0] = this.getTilePos(playerPos);
        this.playerTile[1] = this.getTilePos(cc.v2(playerObj1.x, playerObj1.y));
        this.enemyTile = this.getTilePos(enemyPos);
        //设置敌人位置
        var pos2 = this.mainLayer.getPositionAt(this.enemyTile);
        this.enemy.setPosition(pos2);
        this.enemyDir = DIR.RIGHT;
        // //更新玩家位置
        this.updatePlayerPos();
        // this.playerDir = DIR.DOWN;
    }

    updatePlayerPos() {
        let pos = this.mainLayer.getPositionAt(this.playerTile[0]);
        this.player.setPosition(pos.x, pos.y)
        let pos1 = this.mainLayer.getPositionAt(this.playerTile[1]);
        this.player1.setPosition(pos1.x, pos1.y)
    }

    /**
     * 转换坐标为瓦片坐标，如(0,0) (0,1)
     * @param posInPixel 
     */
    getTilePos(posInPixel: cc.Vec2) {
        var mapSize = this.node.getContentSize();
        var tileSize = this.map.getTileSize();
        var x = Math.floor(posInPixel.x / tileSize.width);
        var y = Math.floor((mapSize.height - posInPixel.y) / tileSize.height);
        return cc.v2(x, y);
    }

    /**
     * 放炸弹
     */
    placeBomb(event, bomdPos) {
        this.bomb = cc.instantiate(this.bombPrefab);
        if (bomdPos) {
            let tmpPos = JSON.parse(bomdPos)
            this.bombTile[this.playerIndex] = cc.v2(tmpPos.x, tmpPos.y)
        } else {
            this.bombTile[this.playerIndex] = this.playerTile[this.playerIndex];
            let pos = new Object;
            pos.x = this.bombTile[this.playerIndex].x;
            pos.y = this.bombTile[this.playerIndex].y;
            this.gameManager.roomSocket.emit('place bomb', JSON.stringify(pos));
        }
        cc.log(this.bombTile)
        this.bomb.setPosition(this.mainLayer.getPositionAt(this.bombTile[this.playerIndex]));
        this.node.addChild(this.bomb);
    }

    /**
     * 获取砖块类型
     * @param layer 
     * @param tile 
     */
    getTileType(layer: cc.TiledLayer, tile: cc.Vec2) {
        var prop = this.map.getPropertiesForGID(layer.getTileGIDAt(tile));
        if (prop)
            return prop.type;
        else
            return null;
    }

    update(deltaTime: number) {
        if (this.moveLeft) {
            this.player.x--;
        }
        //简单怪物逻辑
        if (this.enemyDir == DIR.RIGHT) {
            this.enemy.x++;
            if (this.enemy.x > 544 - 32) {
                this.enemyDir = DIR.LEFT;
            }
        } else {
            this.enemy.x--;
            if (this.enemy.x < 32 + 32) {
                this.enemyDir = DIR.RIGHT;
            }
        }
        this.enemyTile = this.getTilePos(cc.v2(this.enemy.x, this.enemy.y));
        if (this.player.getPosition().sub(this.enemy.getPosition()).mag() < 32) {
            if (!this.panelShow) {
                this.endPanel.active = true;
                this.panelShow = true;
                this.player.getComponent(cc.Animation).play();
            }
        }
    }

    /**
     * 重新加载场景
     */
    reloadScene() {
        cc.director.loadScene('main');
        cc.director.resume();
    }
}
